%%%-------------------------------------------------------------------
%%% @author Rain
%%% @doc 游戏日志相关设置
%%% @end
%%%-------------------------------------------------------------------
-module(game_log).
-author("Rain").
-include("log.hrl").

%% API
-export([init_logger/1]).
-export([set_log_level/1, set_log_level/2]).
-export([init_app_logger/0]).
-export([log/2, log/3]).


init_app_logger() ->
    TimeStr = game_util_time:date_time_str(),
    SaslLogName = filename:join([?LOG_PATH, "sasl", "sasl_" ++ TimeStr ++ ".log"]),
    application:set_env(kernel, logger_sasl_compatible, true),
    application:set_env(sasl, errlog_type, error),
    application:set_env(sasl, sasl_error_logger, {file, SaslLogName}).


init_logger(GameAppName) ->
    LogLevel = game_log_config:get(log_level, warning),
    LogConsole = game_log_config:get(log_console, false),
    logger:set_primary_config(level, LogLevel),
    maybe_add_file_logger(GameAppName, LogLevel),
    maybe_add_consult_logger(GameAppName, LogConsole, LogLevel),
    ok = logger:add_handlers(GameAppName),
%%    log_test(),
    ok.

%% @doc 日志外部接口
log(LogType, Format) ->
    log(LogType, Format, []).
log(debug, Format, Args) ->
    ?LOG_DEBUG(Format, Args);
log(info, Format, Args) ->
    ?LOG_INFO(Format, Args);
log(warning, Format, Args) ->
    ?LOG_WARN(Format, Args);
log(error, Format, Args) ->
    ?LOG_ERROR(Format, Args).


log_test() ->
    ?LOG_DEBUG("~p ", [?LINE]),
    ?LOG_INFO("~p ", [?LINE]),
    ?LOG_WARN("~p ", [?LINE]),
    ?LOG_ERROR("~p ", [?LINE]),
    ok.


%% @doc 临时设置日志等级
set_log_level(LogLevel) ->
    LogConsole = game_log_config:get(log_console, false),
    set_log_level(LogLevel, LogConsole).
set_log_level(LogLevel, LogConsole) ->
    {LogLevel, LogConsole}.

maybe_add_file_logger(AppName, LogLevel) ->
    case logger:compare_levels(LogLevel, warning) of
        lt -> % 设置的等级小于warning的，添加debug数据文件轮转
            add_debug_file_logger(AppName, LogLevel);
        _ ->
            pass
    end,
    add_warning_file_logger(AppName, LogLevel),
    ok.


-spec format_cfg() -> LogFormatCfg when
    LogFormatCfg :: logger_formatter:config().
format_cfg() ->
    %% logger_h_common:try_format => Formatter:format(Log,FormatterConfig)
    % 参考 logger_formatter:add_default_config里面的默认选项，不需要重复设置的就不重复设置了
    % templat里面的数据从 ?LOG_META(LogLevelShow) 获得，系统默认带有level,msg和logger:add_default_metadata里面的pid,gl,time

    % gl: group_leader
    % 具体参考 logger:do_log_allowed是如何传参的和logger_formatter是如何使用的
    Template = [log_lv_show," ",time,":", "\n"
        "(MOD:FUN) ", mod, ":", func, " (LINE) ", line, " (PID) ", pid, "\n(MSG) ",
        msg, "\n\n"],
    %  ?DEBUG("Hello ~n World"),
    %  [DEUBG] 2018-05-17 18:31:31.152864+02:00
    %  [MOD:FUN] MetaMod:MateFunc    [LINE] MetaLine    [PID] Pid
    %  Hello
    %  World

    #{depth => 300,
        max_size => 20000,
        single_line => true,
        time_designator => $ , % 时间连接字符
        template => Template
    }.

default_filters_cfg() ->
    #{
        filter_default => stop,
        filters => defalult_handler_filters()
    }.

defalult_handler_filters() ->
    ?DEFAULT_HANDLER_FILTERS([otp, sasl]).


add_debug_file_logger(AppName, LogLevel) ->
    % config参考官网对logger_std_h的参数说明
    Config = #{level => LogLevel,
        formatter => {logger_formatter, format_cfg()},
        config => #{
            file => filename:join(?LOG_PATH, "debug_")
        }
    },
    AddHandler = {handler, game_log_debug_handler, game_logger_std, Config},
    add_app_handler(AppName, AddHandler).


add_warning_file_logger(AppName, LogLevel) ->
    LevelFilter = {level, {fun logger_filters:level/2, {stop, lt, warning}}},
    Config = #{level => LogLevel,
        formatter => {logger_formatter, format_cfg()},
        config => #{
            file => filename:join(?LOG_PATH, "warn_")
        },
        filters => [LevelFilter | defalult_handler_filters()]
    },
    AddHandler = {handler, game_log_warn_handler, game_logger_std, Config},
    add_app_handler(AppName, AddHandler).

add_app_handler(AppName, {handler, Id, Module, Config}) ->
    Config1 = maps:merge(default_filters_cfg(), Config),
    Handler1 = {handler, Id, Module, Config1},
    Handlers = application:get_env(AppName, logger, []),
    Handlers1 = lists:keystore(Id, 2, Handlers, Handler1),
    application:set_env(AppName, logger, Handlers1).



maybe_add_consult_logger(AppName, true, LogLevel) ->
    % 默认就是standard_io
    Config = #{level => LogLevel,
        formatter => {logger_formatter, format_cfg()}
    },
    AddHandler = {handler, game_log_console_handler, logger_std_h, Config},
    add_app_handler(AppName, AddHandler),
    ok;
maybe_add_consult_logger(_, _, _) ->
    pass.



